package com.hmily.dubbo.provider.async;

import org.apache.commons.lang3.time.FastDateFormat;

import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * <h1>CompletableFuture 样例代码。</h1>
 *
 * @author hmilyylimh
 * ^_^
 * @version 0.0.1
 * ^_^
 * @date 2022-04-09
 */
public class CompletableFutureSample {

    public static void main(String[] args) throws Throwable {
        main_get();
        main_runAsync_Runnable();
        main_supplyAsync_Supplier();
        main_thenRun();
        main_thenAccept();
        main_thenApply();
    }

private static void main_get() throws Throwable {
    String methodName = "main_get";
    CompletableFuture<String> future = new CompletableFuture<>();
    new Thread(() -> {
        sleepInner(2000);
        future.complete("After sleep 2000ms");
    }).start();
    System.out.println(methodName + " 开始执行, now: " + now());
    System.out.println(methodName + " 拿到结果, 结果为: " + future.get() + ", now: " + now());
    System.out.println("-------------------------------");
}

private static void main_runAsync_Runnable() throws Throwable {
    String methodName = "main_runAsync_Runnable";
    CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
        @Override
        public void run() {
            sleepInner(2000);
        }
    });
    System.out.println(methodName + " 开始执行, now: " + now());
    future.get();
    System.out.println(methodName + " 执行完成, now: " + now());
    System.out.println("-------------------------------");
}

private static void main_supplyAsync_Supplier() throws Throwable {
    String methodName = "main_supplyAsync_Supplier";
    CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            sleepInner(2000);
            return "After sleep 2000ms";
        }
    });
    System.out.println(methodName + " 开始执行, now: " + now());
    System.out.println(methodName + " 拿到结果, 结果为: " + future.get() + ", now: " + now());
    System.out.println("-------------------------------");
}

private static void main_thenRun() throws Throwable {
    String methodName = "main_thenRun";
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            sleepInner(2000);
            return "After sleep 2000ms";
        }
    }).thenRun(new Runnable() {
        @Override
        public void run() {
            sleepInner(2000);
        }
    });
    System.out.println(methodName + " 开始执行, now: " + now());
    System.out.println(methodName + " 拿到结果, 结果为: " + future.get() + ", now: " + now());
    System.out.println("-------------------------------");
}

private static void main_thenAccept() throws Throwable {
    String methodName = "main_thenAccept";
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            sleepInner(2000);
            return "After sleep 2000ms";
        }
    }).thenAccept(new Consumer<String>() {
        @Override
        public void accept(String s) {
            sleepInner(2000);
            String result = s + ", Again 2000ms.";
            System.out.println(methodName + " 继续两秒, 中途计算结果为: " + result + ", now: " + now());
        }
    });
    System.out.println(methodName + " 开始执行, now: " + now());
    System.out.println(methodName + " 拿到结果, 结果为: " + future.get() + ", now: " + now());
    System.out.println("-------------------------------");
}

private static void main_thenApply() throws Throwable {
    String methodName = "main_thenApply";
    CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            sleepInner(2000);
            return "After sleep 2000ms";
        }
    }).thenApply(new Function<String, String>() {
        @Override
        public String apply(String s) {
            sleepInner(2000);
            String result = s + ", Again 2000ms.";
            return result;
        }
    });
    System.out.println(methodName + " 开始执行, now: " + now());
    System.out.println(methodName + " 拿到结果, 结果为: " + future.get() + ", now: " + now());
    System.out.println("-------------------------------");
}

    private static void sleepInner(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static String now() {
        return FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
    }
}
